#include "BSException/BSException.h"
#include "boost/property_tree/ptree.hpp"
#include "boost/property_tree/ini_parser.hpp"
#include "Ini.h"

using namespace SystemTool::IO;

// Construct the ini 
Ini::Ini():
	m_strFilePath(""),
	m_bDisposed(false)
{

}

// Destory the ini
Ini::~Ini()
{
	if (!GetDisposed())
	{
		SetDisposed(true);

		SetFilePath("");
	}
}

// Copy the ini
Ini::Ini(const Ini& other)
{
	SetFilePath(other.GetFilePath());

	SetDisposed(other.GetDisposed());
}

// Assign the ini
Ini& Ini::operator=(const Ini& other)
{
	if (this != &other)
	{
		SetFilePath(other.GetFilePath());

		SetDisposed(other.GetDisposed());
	}

	return *this;
}

// Configure the ini file path
void Ini::Configure(std::string strFilePath)
{
	SetFilePath(strFilePath);

	boost::property_tree::ptree lvptProperties;

	try
	{
		try
		{
			boost::property_tree::ini_parser::read_ini(strFilePath, lvptProperties);
		}
		catch (const std::exception& e)
		{
			throw BSException() << e.what();
		}
	}
	catch (BSException& e)
	{
		throw e;
	}
}

// Get key value
template<class T>
bool Ini::GetKeyValue(std::string strSessionName, std::string strKey, T& value)
{
	if (strSessionName.empty())
	{
		return false;
	}

	if (strKey.empty())
	{
		return false;
	}

	std::string strFilePath = GetFilePath();

	if (strFilePath.empty())
	{
		throw BSException() << "Ini file path is empty!";

		return false;
	}

	boost::property_tree::ptree lvptProperties;

	boost::property_tree::ini_parser::read_ini(strFilePath, lvptProperties);

	boost::property_tree::basic_ptree<std::string, std::string> lvbtItems = lvptProperties.get_child(strSessionName);

	try
	{
		try
		{
			value = lvbtItems.get<T>(strKey);
		}
		catch (const std::exception& e)
		{
			throw BSException() << e.what();
		}
	}
	catch (BSException& e)
	{
		throw e;
	}

	return true;
}

// Get key 
bool Ini::GetKey(std::string strSessionName, std::string strKey, std::string& strValue)
{
	return GetKeyValue<std::string>(strSessionName, strKey, strValue);
}

// Get key 
bool Ini::GetKey(std::string strSessionName, std::string strKey, int& iValue)
{
	return GetKeyValue<int>(strSessionName, strKey, iValue);
}

// Get key 
bool Ini::GetKey(std::string strSessionName, std::string strKey, double& dValue)
{
	return GetKeyValue<double>(strSessionName, strKey, dValue);
}

// Get key 
bool Ini::GetKey(std::string strSessionName, std::string strKey, bool& bValue)
{
	return GetKeyValue<bool>(strSessionName, strKey, bValue);
}

// Set key value
template<class T>
bool Ini::SetKeyValue(std::string strSessionName, std::string strKey, T& value)
{
	if (strSessionName.empty())
	{
		return false;
	}

	if (strKey.empty())
	{
		return false;
	}

	std::string strFilePath = GetFilePath();

	if (strFilePath.empty())
	{
		throw BSException() << "Ini file path is empty!";

		return false;
	}

	boost::property_tree::ptree lvptProperties;

	boost::property_tree::ini_parser::read_ini(strFilePath, lvptProperties);

	try
	{
		try
		{
			std::string strAppName = strSessionName + "." + strKey;

			lvptProperties.put<T>(strAppName, value);

			boost::property_tree::ini_parser::write_ini(strFilePath, lvptProperties);
		}
		catch (const std::exception& e)
		{
			throw BSException() << e.what();
		}
	}
	catch (BSException& e)
	{
		throw e;
	}

	return true;
}

// Set key 
bool Ini::SetKey(std::string strSessionName, std::string strKey, std::string strValue)
{
	return SetKeyValue<std::string>(strSessionName, strKey, strValue);
}

// Set key 
bool Ini::SetKey(std::string strSessionName, std::string strKey, int iValue)
{
	return SetKeyValue<int>(strSessionName, strKey, iValue);
}

// Set key 
bool Ini::SetKey(std::string strSessionName, std::string strKey, double dValue)
{
	return SetKeyValue<double>(strSessionName, strKey, dValue);
}

// Set key 
bool Ini::SetKey(std::string strSessionName, std::string strKey, bool bValue)
{
	return SetKeyValue<bool>(strSessionName, strKey, bValue);
}
